#include "oj_compile_run/oj_compile_run.h"
namespace ojlb {
namespace oj_compiler_run {

// public:
void OjCompileRun::start(const std::string& in_json_str, std::string& out_json_str) { // TODO: 这里的代码有一些臃肿, 可以尝试重构
    // 初步制定要返回的 json 值
    Json::Value out_json;
    static std::atomic_uint id(0);
    int64_t time_stamp = oj_common::OjTime::getTimestamp();
    out_json["status"] = 0;
    out_json["reason"] = statusToReason(out_json["status"].asInt());
    out_json["code_stdout"] = "";
    out_json["code_stderr"] = "";
    out_json["time_stamp"] = time_stamp;
    out_json["id"] = static_cast<uint>(id);
    // TODO: json 解析异常的异常还没抛出...

    // 反序列化 json 字符串得到数据
    Json::Value in_json;
    oj_common::OjTransfer::deserialize(in_json_str, in_json);
    std::string user = in_json["user"].asString(); // TODO: json 解析出错时的异常
    std::string title = in_json["title"].asString();
    std::string code = in_json["code"].asString();
    std::string programming_language = in_json["programming_language"].asString();
    int cpu_limit = in_json["cpu_limit"].asInt();
    int mem_limit = in_json["mem_limit"].asInt();
    std::string code_input = in_json["code_input"].asString(); // TODO: 暂不处理

    if (code.size() == 0) {
        oj_common::OjLog::debug("用户 {} 在题目 {} 提交了空文件", user, title);
        out_json["status"] = 1;
        out_json["reason"] = statusToReason(out_json["status"].asInt());
        oj_common::OjTransfer::serialize(out_json, out_json_str);
        return;
    }

    // 组合得到用户代码文件的路径
    std::string path = "./title";
    path += "/";
    path += title;
    path += "/";
    path += user;
    path += "_";
    path += out_json["time_stamp"].asString();
    path += "_";
    path += out_json["id"].asString();
    ++id; // 使用完 id 值后再 ++, 不然空文件时浪费了一个 id 值

    oj_common::OjCodeFile oj_code_file(path, programming_language); // TODO: 文件版本切换为数据库时可以修改一下...

    // 保存用户的代码到本地
    oj_common::OjTransfer::stringToFile(code, oj_code_file.getSourcePath());

    // 使用虚拟编译器进行编译
    if (!OjCompiler::compile(oj_code_file)) {
        // 编译失败
        oj_common::OjLog::debug("用户 {} 在题目 {} 处编译失败", user, title);
        
        out_json["status"] = 2;
        out_json["reason"] = statusToReason(out_json["status"].asInt());
        std::string com_error_message;
        oj_common::OjTransfer::fileToString(oj_code_file.getErrorPath(), com_error_message);
        out_json["code_stderr"] = com_error_message;
        
        oj_common::OjTransfer::serialize(out_json, out_json_str);
        return;
    }

    // 使用虚拟运行器进行运行
    std::pair<bool, int> run_result = OjRuner::run(oj_code_file, cpu_limit, mem_limit);
    if (!run_result.first) {
        // 运行异常
        oj_common::OjLog::debug("用户 {} 在题目 {} 处运行失败", user, title);

        // TODO: 这里的报错最好做区分, 运行出错有可能是用户代码问题, 也有可能是资源限制问题
        out_json["status"] = 3;
        out_json["reason"] = statusToReason(out_json["status"].asInt());
        std::string run_error_message;
        oj_common::OjTransfer::fileToString(oj_code_file.getErrorPath(), run_error_message);
        out_json["code_stderr"] = run_error_message;

        oj_common::OjTransfer::serialize(out_json, out_json_str);
        return;
    }

    // 返回响应结果给用户
    std::string ran_message;
    oj_common::OjTransfer::fileToString(oj_code_file.getResultPath(), ran_message);
    out_json["code_stdout"] = ran_message;
    oj_common::OjTransfer::serialize(out_json, out_json_str);
}

// private:
std::string OjCompileRun::statusToReason(const int& status) {
    // 请求成功(0), 代码为空(1), 编译出错(2), 运行异常(3)
    if (status == 0) {
        return "succeed";
    } else if (status == 1) {
        return "null code";
    } else if (status == 2) {
        return "compile error";
    } else if (status == 3) {
        return "run error";
    } else {
        return "unknown error";
    }
}


}
}
